/****************************************************************************
**
** Copyright (C) 2013 Atmel Corporation and/or its subsidiary(-ies).
** All rights reserved.
**
** LIMITED License Agreement
**
** IT IS IMPORTANT THAT YOU READ THIS AGREEMENT CAREFULLY AND COMPLETELY.
** This Limited License Agreement (“Agreement”) is a legally binding agreement between,
** on one hand, either your employer (if you are acting on behalf of your employer)
** or you (if you are acting on your own behalf) (“Licensee”), and on the other hand,
** Atmel Corporation (“Atmel”).
**
** By installing or using any of the software downloaded or provided with these
** terms (“Licensed Software”), you are indicating that you are binding Licensee
** to the terms of this Agreement, and that you are duly authorized by Licensee to do so.
** If you are not authorized to bind Licensee to the terms of this Agreement,
** or if Licensee does not agree to be bound by all of the terms of this Agreement,
** do not install or use any such software.
**
**
** 1.	Grant of License.  Subject to the terms and conditions of this Agreement,
** Atmel grants Licensee a non-exclusive, non-transferable, non-sublicensable,
** limited license to use the Licensed Software solely in connection with Atmel products
** from SAM9 and SAMA5 families (“Atmel Product”).
**
** 2.	Restrictions.  Except as expressly set forth in Section 1, Licensee will not,
** and will have no right to, (a) use, copy or reproduce any Licensed Software except,
** (b) modify, create derivative works of, sell, distribute, transfer or disclose any
** Licensed Software. Without limiting the generality of the foregoing, Licensee will not,
** and will have no right to, use any Licensed Software for any semiconductor products
** that are not Atmel Products. Licensee will not remove, obscure or alter any trademark,
** copyright or other proprietary rights or ownership notices of Atmel that appear
** in any Licensed Software.
**
** 3.  	Title.  As between the parties, Atmel retains full rights, title, and ownership
** including all patents, copyrights, trade secrets, trade names, trademarks, and other
** intellectual property rights in and to the Licensed Software.
**
** 4.  	No Other Rights.  Except as expressly stated herein, this Agreement does not grant
** Licensee any rights to patents, copyrights, trade secrets, trade names, trademarks
** (whether registered or unregistered), or any other rights, franchises, or licenses
** in respect of the Licensed Software.
**
** 5.	Disclaimer of Warranty and No Support.  ALL LICENSED SOFTWARE IS PROVIDED “AS IS”,
** “WITH ALL FAULTS”, AND WITH NO WARRANTY WHATSOEVER.  ATMEL EXPRESSLY DISCLAIMS ALL
** WARRANTIES OF ANY KIND (WHEHTER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE) IN CONNECTION
** WITH THE LICENSED SOFTWARE OR ANY OTHER ASPECT OF THIS AGREEMENT, INCLUDING, WITHOUT
** LIMITATION ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
** TITLE OR NON-INFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY WARRANTIES THAT MAY ARISE
** FROM COURSE OF DEALING, COURSE OF PERFORMANCE OR USAGE OF TRADE.  ATMEL WILL HAVE
** NO OBLIGATION UNDER THIS AGREEMENT TO CORRECT ANY BUGS, DEFECTS OR ERRORS IN
** THE LICENSED SOFTWARE, PROVIDE ANY UPDATES, UPGRADES OR NEW RELEASES OF THE LICENSED SOFTWARE,
** OR OTHERWISE PROVIDE ANY SUPPORT OR MAINTENANCE FOR THE LICENSED SOFTWARE.
**
** 6.  	Export.  Licensee will comply with all applicable laws and regulations of all
** relevant jurisdictions in connection with its activities related to the Licensed Software.
** Without limitation of the foregoing, Licensee acknowledges that certain laws
** and regulations of the United States and other jurisdictions may pertain to the export
** and re-export of the Licensed Software, and Licensee will not export or re-export
** any Licensed Software in any form without the appropriate governmental approvals,
** or otherwise in violation of any such laws or regulations.
**
** 7.	Termination.  The license will automatically terminate if Licensee fails to comply
** with any of the terms and conditions of the license including, without limitation
** the confidentiality obligation or the obligations set forth in Sections 1, 2, 6, 7, 10
** and 11 herein. Upon termination for any reason, Licensee will immediately destroy
** or return to Atmel all whole or partial copies of the Licensed Software.
**
** 8.	High Risk Activities. LICENSEE ACKNOWLEDGES AND AGREES THAT THE LICENSED SOFTWARE
** IS NOT DESIGNED OR APPROVED FOR, AND WILL NOT BE INCORPORATED (WITHOUT THE EXPRESS WRITTEN
** APPROVAL OF AN OFFICER OF ATMEL) INTO, ANY PRODUCTS THAT ARE USED OR DESIGNED TO BE USED
** IN CONNECTION WITH ANY ACTIVITIES WHERE THE FAILURE OF SUCH PRODUCTS COULD REASONABLY
** BE EXPECTED TO RESULT IN DEATH, BODILY INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE
** ("HIGH RISK ACTIVITIES").  IN NO EVENT WILL ATMEL HAVE ANY LIABILITY TO LICENSEE
** OR ANY THIRD PARTY ARISING OUT OF OR RELATED TO ANY USE OF LICENSED SOFTWARE IN CONNECTION
** WITH HIGH RISK ACTIVITIES, AND ATMEL HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF
** FITNESS FOR ANY HIGH RISK ACTIVITIES.
**
** 9.  	LIMITATION OF LIABILITY.  TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
** ATMEL BE LIABLE TO LICENSEE OR ANY THIRD PARTY (WHETHER SUCH LIABILITY IS BASED ON CONTRACT,
** NEGLIGENCE, STRICT LIABILITY, OTHER TORT THEORY, CONTRIBUTION, BREACH OF WARRANTY,
** OR OTHER LEGAL OR EQUITABLE THEORY) FOR ANY SPECIAL, INDIRECT, INCIDENTAL, EXEMPLARY,
** PUNITIVE OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES FOR LOSS OF PROFITS,
** LOSS OR INTERRUPTION OF BUSINESS, OR LOSS OF DATA, ARISING OUT OF OR RELATING TO
** THE LICENSED SOFTWARE OR ANY OTHER ASPECT OF THIS AGREEMENT, EVEN IF ATMEL has been advised
** of or should have known of the possibility of such damages.
**
** IN NO EVENT WILL ATMEL’S TOTAL LIABILITY ARISING OUT OF OR RELATED TO THE LICENSED SOFTWARE
** OR ANY OTHER ASPECT OF THIS AGREEMENT (WHETHER UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY,
** CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL OR EQUITABLE THEORY) EXCEED THE GREATER OF
** (A) THE AGGREGATE OF ALL LICENSE FEES PAID BY LICENSEE TO ATMEL FOR THE LICENSED SOFTWARE, OR
** (B) ONE THOUSAND DOLLARS ($1,000). WITHOUT LIMITING THE FOREGOING,
** AND Notwithstanding any provision herein to the contrary, ATMEL will not be liable for
** ANY costs of PROCURING SUBSTITUTE GOODS, SERVICES OR TECHNOLOGY under any circumstances.
**
** Each Party acknowledges that THE OTHER PARTY has entered into this agreement in reliance
** on the limitations of liability, DISCLAIMERS OF WARRANTIES, EXCLUSION OF DAMAGES
** AND EXCLUSIVE REMEDIES contained in this AGREEMENT, AND THAT EACH OF THE FOREGOING PROVISIONS FORMS
** AN ESSENTIAL AND fundamental part of the basis of the bargain BETWEEN THE PARTIES,
** WITHOUT WHICH SUCH the other Party would not have entered into this Agreement.
** EACH PARTY AGREES THAT SUCH PROVISIONS WILL SURVIVE AND APPLY NOTWITHSTANDING ANY
** FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY OR LIMITATION OF LIABILITY.
**
** 10.  	Governing Law; Dispute Resolution. This Agreement is to be construed in accordance
** with and governed by the internal laws of the State of California (as permitted by Section 1646.5
** of the California Civil Code or any similar successor provision), without giving effect
** to any choice of law rule that would cause the application of the laws of any jurisdiction
** other than the internal laws of the State of California to the rights and duties of the parties.
** This Agreement will not be governed by the U.N. Convention on the Sale of Goods,
** the application of which is expressly excluded. Except for actions for injunctive
** or other equitable relief, which may be brought in any court of competent jurisdiction,
** all disputes arising out of or related to this Agreement will be subject to the exclusive
** jurisdiction of the California state courts in Santa Clara County, California,
** or if there is exclusive federal jurisdiction, the United States District Court for
** the Northern District of California, and the Parties hereby consent to, and agree to submit to,
** the personal and exclusive jurisdiction and venue of such courts.
**
** 11. 	General. Licensee will not, and will have no right to, assign, delegate or otherwise
** transfer (whether voluntarily, by operation of law or otherwise) this Agreement or any of
** its rights or obligations hereunder to any third party without the prior written consent
** of Atmel, and any purported assignment, delegation or other transfer without such consent
** will have no force or effect. Subject to the foregoing, this Agreement will be binding upon
** and will inure to the benefit of the parties and their respective successors and permitted assigns.
** No failure of either party to enforce any right under this Agreement will be deemed a waiver
** of such right or any other right under this Agreement. Any waiver by a party of a breach
** of any provision of this Agreement by the other party hereunder will not be deemed to be
** a waiver of any subsequent breach of such provision or a waiver of any breach of any other
** provision of this Agreement.
** This Agreement may not be superseded, modified, or amended except in a writing signed by an officer
** of each party. If any provision of this Agreement is determined to be invalid, illegal
** or otherwise unenforceable, such provision will be enforced to the extent possible consistent
** with the intent of the parties, and the remaining provisions of this Agreement will remain in
** full force and effect. This Agreement will be fairly interpreted in accordance with its terms
** and without any strict construction against either party because it was drafted by such party
** or for any other reason. This Agreement will constitute the entire agreement between the parties
** relating to the subject matter hereof, and expressly supersedes and replaces all prior
** and contemporaneous agreements, proposals, quotations, negotiations and communications, written
** or oral, between the parties relating to such subject matter.
**
**
** Software Author: Timesys Corporation (www.timesys.com)
**
** Summary: Qt UI handling class for the MainWindow. All Widgets and Views are nested in this
**          object when showing on LCD display
**
****************************************************************************/


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "helpscreen.h"
#include "maincontrols.h"
#include "settingsscreen.h"
#include "hvacscreen.h"
#include "homescreen.h"
#include "securityscreen.h"
#include "lightingscreen.h"
#include "mediascreen.h"

#include "MicroCounter.h"
#include <QCoreApplication>

/***
 ** Default constructor
 ** - Initialize Primary Screen that will show up at boot time and show it first
 ** with an hourglass and text "Loading..."
 ** - Initialize remaining funtionality in the second step after showing initial screen by
 ** usinge a single shot timer object.
 ** - Connect signals with handlers for initialized objects
 ** - Show the application in the Full Screen Mode
 **/
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    ui->stackedWidget->setSpeed(transition_speed);

    float wSFactor;
    float hSFactor;
    if (isSmallResolution) {
        wSFactor = 480.0 / 800.;
        hSFactor = 272.0 / 480.;

        setMaximumSize(480, 272);
        setGeometry(0, 0, 480, 272);
        ui->centralWidget->setMaximumSize(480, 272);
        ui->centralWidget->setGeometry(0, 0, 480, 272);
        DayWeather::sNormalIconSize = QSize(55,55);
        DayWeather::sLargeIconSize = QSize(130,130);
        qDebug() << "wFactor: " << wSFactor;
        qDebug() << "hFactor: " << hSFactor;
    }


    ui->stackedWidget->setVerticalMode(false);
    ui->stackedWidget->setCurrentIndex(0);       //set the initial page to Help page

    helpScreen = NULL;
    mediaScreen = NULL;
    lightScreen = NULL;
    securityScreen = NULL;


    if (!isSmallResolution) {
        mcontrols = new MainControls();
        ui->controlButtonsLayout->addWidget(mcontrols);

        QObject::connect(mcontrols, SIGNAL(settingsRequested()), this, SLOT(switchToSettingsScreen()));
        QObject::connect(mcontrols, SIGNAL(helpRequested()), this, SLOT(switchToHelpScreen()));
        QObject::connect(mcontrols, SIGNAL(homeRequested()), this, SLOT(switchToHomeScreen()));
    }

    homeScreen = new HomeScreen(this);
    ui->pageHomeLayout->addWidget(homeScreen);

    QObject::connect(ui->stackedWidget, SIGNAL(animationFinished()), this, SLOT(windowSwitchingDone()));
    QObject::connect(homeScreen, SIGNAL(settingsRequested()), this, SLOT(switchToSettingsScreen()));
    QObject::connect(homeScreen, SIGNAL(helpRequested()), this, SLOT(switchToHelpScreen()));
    QObject::connect(homeScreen, SIGNAL(climateRequested()), this, SLOT(switchToClimateScreen()));
    QObject::connect(homeScreen, SIGNAL(lightingRequested()), this, SLOT(switchToLightingScreen()));
    QObject::connect(homeScreen, SIGNAL(securityRequested()), this, SLOT(switchToSecurityScreen()));
    QObject::connect(homeScreen, SIGNAL(mediaRequested()), this, SLOT(switchToMediaScreen()));

    this->showFullScreen();

    helpScreen = new HelpScreen();
    ui->pageHelpLayout->addWidget(helpScreen);

    this->setEnabled(false);
    homeScreen->startProgress();

    //Delay the init of most screens till after I show the initial screen
    QTimer::singleShot(300, this, SLOT(delayedInitProcess()));
}

/***
 ** Default destructor
 **/
MainWindow::~MainWindow()
{
    delete ui;
}

/***
 ** Handler method for the Settings button
 ** Switch visible screen to Settings using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToSettingsScreen()
{
    ui->stackedWidget->slideInIdx(5);
    ui->stackedWidget->setFocus();
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Handler method for the Help button
 ** Switch visible screen to Help using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToHelpScreen()
{
	if(helpScreen == NULL){
        helpScreen = new HelpScreen();
        ui->pageHelpLayout->addWidget(helpScreen);
	}

    ui->stackedWidget->slideInIdx(1);
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
}

/***
 ** Handler method for the Climate button
 ** Switch visible screen to Climate using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToClimateScreen()
{
    ui->stackedWidget->slideInIdx(2);
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Handler method for the Lighting button
 ** Switch visible screen to Lighting using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 ** Update names for Lighting Zones/Rooms
**/
void MainWindow::switchToLightingScreen()
{
	if(lightScreen == NULL)
	{
		lightScreen = new LightingScreen();
		ui->pageLightingLayout->addWidget(lightScreen);

		LightingSettings* lightingSettings = settingsScreen->getLightingSettings();
		QObject::connect(lightingSettings, SIGNAL(roomNamesChanged(QList<QStringList>&)), lightScreen, SLOT(setLighingRoomNames(QList<QStringList>&)));

	}
    ui->stackedWidget->slideInIdx(4);
    settingsScreen->populateLightingZones();
    settingsScreen->getLightingSettings()->updateData();
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Handler method for the Settings button
 ** Switch visible screen to Settings using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToSecurityScreen()
{
    if(securityScreen == NULL)
    {
        securityScreen = new SecurityScreen();
        ui->pageSecurityLayout->addWidget(securityScreen);

        SecuritySettings* securitySettings  = settingsScreen->getSecuritySettings();
        QObject::connect(securitySettings, SIGNAL(securityZonesChanged(QStringList&)), securityScreen, SLOT(setSecurityZoneNames(QStringList&)));

    }
    ui->stackedWidget->slideInIdx(3);
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Handler method for the Media button
 ** Switch visible screen to Media using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToMediaScreen()
{
	if(mediaScreen == NULL)
	{
        mediaScreen = new MediaScreen();
		ui->pageMediaLayout->addWidget(mediaScreen);

		MediaSettings* mediaSettings = settingsScreen->getMediaSettings();
		QObject::connect(mediaSettings, SIGNAL(mediaRoomsChanged(QStringList&)), mediaScreen, SLOT(setMediaRoomNames(QStringList&)));
	}

    ui->stackedWidget->slideInIdx(6);
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Handler method for the Home button
 ** Switch visible screen to Home using custom stackedWidget transition
 ** Set Security and Help screens to a default state (avoid CPU consumption in background)
 **/
void MainWindow::switchToHomeScreen()
{
    overlayControls->setVisible(false);

    if (!isSmallResolution)
        mcontrols->setVisible(false);

    ui->stackedWidget->slideInIdx(0, 0);
    if(securityScreen)
        securityScreen->turnOffCameras();
    if(helpScreen)
        helpScreen->stopVideoPlayback();
    // benchmark();
}

/***
 ** Delayed Init Process.
 ** Starts when the one time Timer kicked off in Constructor expires
 ** Creates remaining objects for screens and handlers for communication
 **/
void MainWindow::delayedInitProcess()
{

    overlayControls = new OverlayControls();
    ui->navigationButtonLayout->addWidget(overlayControls);

    overlayControls->setVisible(false);

//    helpScreen = new HelpScreen();
//    ui->pageHelpLayout->addWidget(helpScreen);

    settingsScreen = new SettingsScreen();
    ui->pageSettingsLayout->addWidget(settingsScreen);

    hvacScreen = new HVACScreen();
    ui->pageHVACLayout->addWidget(hvacScreen);

    securityScreen = new SecurityScreen();
    ui->pageSecurityLayout->addWidget(securityScreen);

    lightScreen = new LightingScreen();
    ui->pageLightingLayout->addWidget(lightScreen);

    mediaScreen = new MediaScreen();
    ui->pageMediaLayout->addWidget(mediaScreen);

    QObject::connect(overlayControls, SIGNAL(climateRequest()), this, SLOT(switchToClimateScreen()));
    QObject::connect(overlayControls, SIGNAL(mediaRequest()), this, SLOT(switchToMediaScreen()));
    QObject::connect(overlayControls, SIGNAL(lightingRequest()), this, SLOT(switchToLightingScreen()));
    QObject::connect(overlayControls, SIGNAL(securityRequest()), this, SLOT(switchToSecurityScreen()));

    if (isSmallResolution) {
        QObject::connect(overlayControls, SIGNAL(homeRequest()), this, SLOT(switchToHomeScreen()));
    }

    QObject::connect(hvacScreen, SIGNAL(requestLabelsforHVAC()), settingsScreen, SLOT(requestedHVACLabels()));
    QObject::connect(settingsScreen, SIGNAL(sendingHVACZonesInfo(QStringList&)), hvacScreen, SLOT(setHVACZonesInfo(QStringList&)));


    PrefsSettings* prefsSettings = settingsScreen->getPrefsSettings();
	LightingSettings* lightingSettings = settingsScreen->getLightingSettings();
	SecuritySettings* securitySettings  = settingsScreen->getSecuritySettings();
	MediaSettings* mediaSettings = settingsScreen->getMediaSettings();

	WeatherWidget* weatherWidget = hvacScreen->getWeatherForcast()->getWeatherWidget();

	QObject::connect(prefsSettings, SIGNAL(zipCodeChanged(int)), weatherWidget, SLOT( updateWeather(int) ));
	QObject::connect(lightingSettings, SIGNAL(roomNamesChanged(QList<QStringList>&)), lightScreen, SLOT(setLighingRoomNames(QList<QStringList>&)));
	QObject::connect(mediaSettings, SIGNAL(mediaRoomsChanged(QStringList&)), mediaScreen, SLOT(setMediaRoomNames(QStringList&)));
	QObject::connect(securitySettings, SIGNAL(securityZonesChanged(QStringList&)), securityScreen, SLOT(setSecurityZoneNames(QStringList&)));
	QObject::connect(prefsSettings, SIGNAL(temperatureChanged(int)), hvacScreen->getHVACSet(), SLOT(setTempUnits(int)));

    settingsScreen->requestedHVACLabels();  //populate the lables for HVAC

    this->setEnabled(true);
    homeScreen->stopProgress();
    // benchmark();
}

/***
 ** When stackedWidget transition animation is done display 2 control panels
 ** - overlay controls (left hand side)
 ** - main controls (right hand side)
 **/
void MainWindow::windowSwitchingDone()
{
    if(ui->stackedWidget->currentIndex() == 0)
    {
        overlayControls->setVisible(false);

        if (!isSmallResolution)
            mcontrols->setVisible(false);
    }else{
        overlayControls->setVisible(true);

        if (!isSmallResolution)
            mcontrols->setVisible(true);
    }

}

/***
 ** Catch the "K1" capacitive button press and close the application
 **/
void MainWindow::keyPressEvent( QKeyEvent *k )
{
    if(k->key() == 48)
        qApp->exit();
}

void MainWindow::benchmark()
{
    qDebug("Starting repaint benchmark...");
    MicroCounter counter;
    int i = 100;
    while (i--) {
        update();
        counter.start();
        QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
        counter.stop();
    }
    qDebug("Average execution of events takes %d [us]", int(counter.averageTime()));
}
